﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

namespace HSDc.DefinitionTransformer.Adapter
{
    //[NUnit.Framework.TestFixture]
    internal class UploadRepositoryAdapter
    {
        private Data.ProcessDefinition psds;
        private Entity.Process _process;
        internal string Upload(Entity.Process process)
        {
            ProcessDataSet(process);
            return GetResultService(psds.GetXml());
        }

        private void ProcessDataSet(Entity.Process process)
        {
            this._process = process;
            psds = new Data.ProcessDefinition();
            Data.ProcessDefinition.ProcessDefinitionRow pdRow = psds._ProcessDefinition.AddProcessDefinitionRow(process.Name, process.Source, Convert.ToInt32(process.Active));
            int ruleCount = 1;
            foreach(var s in process.Swimlanes)
            {
                Data.ProcessDefinition.RuleRow rRow = psds.Rule.AddRuleRow("RULE" + ruleCount, s.RuleClass, "");
                ruleCount += 1;
                Data.ProcessDefinition.SwimlaneRow sRow = psds.Swimlane.AddSwimlaneRow(s.Name, s.SeqNo, rRow, pdRow);
            }
            foreach(var pe in process.ConnectedElements)
            {
                ProcessProcessElement(pdRow, pe, ref ruleCount);
            }
            foreach (var pe in process.Transitions)
            {
                ProcessTransition(pe);
            }
        }

        private void ProcessProcessElement(Data.ProcessDefinition.ProcessDefinitionRow pdRow, Entity.ProcessElement processElement, ref int ruleCount)
        {
            if (processElement.GetType() == typeof(Entity.Decision)) ProcessActivity(pdRow, processElement, "DecisionActivity",ref ruleCount);
            if (processElement.GetType() == typeof(Entity.EndPoint)) ProcessActivity(pdRow, processElement, "EndActivity", ref ruleCount);
            if (processElement.GetType() == typeof(Entity.Activity)) ProcessActivity(pdRow, processElement, "HumanActivity", ref ruleCount);
            if (processElement.GetType() == typeof(Entity.Fork)) ProcessActivity(pdRow, processElement, "ForkActivity", ref ruleCount);
            if (processElement.GetType() == typeof(Entity.Join)) ProcessActivity(pdRow, processElement, "JoinActivity", ref ruleCount);
        }

        private void ProcessActivity(Data.ProcessDefinition.ProcessDefinitionRow pdRow, Entity.ProcessElement element, String activityName, ref int ruleCount)
        {
            Data.ProcessDefinition.RuleRow rRow = null;
            string ruleClass = GetRuleClass(element);
            if (!string.IsNullOrEmpty(ruleClass))
            {
                rRow = psds.Rule.AddRuleRow("RULE" + ruleCount, ruleClass, "");
                ruleCount += 1;
            }
            Data.ProcessDefinition.SwimlaneRow sRow = psds.Swimlane.FindByName(_process.FindElementBelongSwimlane(element.ParentId).Name);
            psds.Activity.AddActivityRow(element.Name, activityName, sRow, rRow, pdRow);
        }

        public string GetRuleClass(Entity.ProcessElement processElement)
        {
            if (processElement.GetType() == typeof(Entity.Decision)) return ((Entity.Decision)processElement).RuleClass;

            return string.Empty;

        }

        private void ProcessTransition(Entity.Transition element)
        {
            Data.ProcessDefinition.ActivityRow sourceRow = psds.Activity.FindByName(_process.FindConnectedProcessElement(element.SourceId).Name);
            Data.ProcessDefinition.ActivityRow targetRow = psds.Activity.FindByName(_process.FindConnectedProcessElement(element.TargetId).Name);
            if ((sourceRow != null) && (targetRow != null))
                psds.Transition.AddTransitionRow(sourceRow, targetRow, element.Constraint);
        }

        private string GetResultService(string xml)
        {
            HttpClient client = new HttpClient();
            Uri uri = new Uri("http://localhost:49187/Repository");
            client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
            xml = System.Uri.EscapeDataString(xml);
            var postData = new List<KeyValuePair<string, string>>();
            postData.Add(new KeyValuePair<string, string>("definitionXml", xml));
            HttpContent content = new FormUrlEncodedContent(postData);
            var response = client.PostAsync(uri, content).Result;
            string result = "";
            if (response.IsSuccessStatusCode)
            {
                result = response.Content.ReadAsStringAsync().Result;
            }
            else
            {
                throw new Exception("Upload Failed !");
            }
            return result;
        }

        //[NUnit.Framework.Test]
        public void TestService()
        {
            string input = @"<?xml version=""1.0""?> <proc:ProcessDefinition xmlns:proc=""http://tempuri.org/ProcessDefinition.xsd"">   <proc:ProcessDefinition>     <proc:DefinitionName>TestDefinition</proc:DefinitionName>     <proc:DefinitionSource></proc:DefinitionSource>     <proc:DefinitionStatus>1</proc:DefinitionStatus>   </proc:ProcessDefinition>   <proc:Swimlane>     <proc:Name>Swimlane1</proc:Name>     <proc:SeqNo>1</proc:SeqNo>     <proc:RuleName>Rule1</proc:RuleName>     <proc:DefinitionName>TestDefinition</proc:DefinitionName>   </proc:Swimlane>   <proc:Rule>     <proc:RuleName>Rule1</proc:RuleName>     <proc:RuleClass>Ringle.Rule.DefaultRule</proc:RuleClass>     <proc:RuleDll>Rule.dll</proc:RuleDll>   </proc:Rule>   <proc:Activity>     <proc:Name>Activity1</proc:Name>     <proc:ActivityClass>HumanActivity</proc:ActivityClass>     <proc:SwimlaneName>Swimlane1</proc:SwimlaneName>     <proc:RuleName>Rule1</proc:RuleName>     <proc:DefinitionName>TestDefinition</proc:DefinitionName>   </proc:Activity>   <proc:Activity>     <proc:Name>Activity2</proc:Name>     <proc:ActivityClass>EndActivity</proc:ActivityClass>     <proc:SwimlaneName>Swimlane1</proc:SwimlaneName>     <proc:RuleName>Rule1</proc:RuleName>     <proc:DefinitionName>TestDefinition</proc:DefinitionName>   </proc:Activity>   <proc:Transition>     <proc:SourceActivityName>Activity1</proc:SourceActivityName>     <proc:TargetActivityName>Activity2</proc:TargetActivityName>     <proc:Constraint></proc:Constraint>   </proc:Transition> </proc:ProcessDefinition>";
            string result = GetResultService(input);
            Console.WriteLine("Definition ID is " + result);
        }
    }
}
